// import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
// import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;

#include "SQLPartitionBy.h"
#include "expr/SQLIntegerExpr.h"
#include "expr/SQLIdentifierExpr.h"

#include "SQLSubPartitionBy.h"
#include "SQLPartition.h"
#include "SQLName.h"
#include "SQLExpr.h"
#include "../../utils/instanceof.h"

SQLPartitionBy::SQLPartitionBy()
{
  partitions = std::make_shared<std::list<SQLPartition_ptr>>();
  storeIn = std::make_shared<std::list<SQLName_ptr>>();
  columns = std::make_shared<std::list<SQLExpr_ptr>>();
}

SQLPartition_list_ptr SQLPartitionBy::getPartitions()
{
  return partitions;
}

void SQLPartitionBy::addPartition(SQLPartition_ptr partition)
{
  if (partition != nullptr)
  {
    partition->setParent(SharedObject(SQLPartitionBy));
  }
  this->partitions->push_back(partition);
}

SQLSubPartitionBy_ptr SQLPartitionBy::getSubPartitionBy()
{
  return subPartitionBy;
}

void SQLPartitionBy::setSubPartitionBy(SQLSubPartitionBy_ptr subPartitionBy)
{
  if (subPartitionBy != nullptr)
  {
    subPartitionBy->setParent(SharedObject(SQLPartitionBy));
  }
  this->subPartitionBy = subPartitionBy;
}

SQLExpr_ptr SQLPartitionBy::getPartitionsCount()
{
  return partitionsCount;
}

void SQLPartitionBy::setPartitionsCount(SQLExpr_ptr x)
{
  if (x != nullptr)
  {
    x->setParent(SharedObject(SQLPartitionBy));
  }
  this->partitionsCount = x;
}

void SQLPartitionBy::setPartitionsCount(int partitionsCount)
{
  this->partitionsCount = SQLIntegerExpr_ptr(new SQLIntegerExpr(partitionsCount));
}

BOOL_ptr SQLPartitionBy::isLinear()
{
  return linear;
}

void SQLPartitionBy::setLinear(BOOL_ptr linear)
{
  this->linear = linear;
}

SQLName_list_ptr SQLPartitionBy::getStoreIn()
{
  return storeIn;
}

SQLExpr_list_ptr  SQLPartitionBy::getColumns()
{
  return columns;
}

void SQLPartitionBy::addColumn(SQLExpr_ptr column)
{
  if (column != nullptr)
  {
    column->setParent(SharedObject(SQLPartitionBy));
  }
  this->columns->push_back(column);
}

void SQLPartitionBy::cloneTo(SQLPartitionBy_ptr x)
{
  if (subPartitionBy != nullptr)
  {
    x->setSubPartitionBy(std::dynamic_pointer_cast<SQLSubPartitionBy>(subPartitionBy->clone()));
  }
  if (partitionsCount != nullptr)
  {
    x->setPartitionsCount(std::dynamic_pointer_cast<SQLExpr>(partitionsCount->clone()));
  }
  x->linear = linear;
  for (SQLPartition_ptr p : *partitions)
  {
    SQLPartition_ptr p2 = std::dynamic_pointer_cast<SQLPartition>(p->clone());
    p2->setParent(SharedObject(SQLPartitionBy));
    x->partitions->push_back(p2);
  }
  for (SQLName_ptr name : *storeIn)
  {
    SQLName_ptr name2 = std::dynamic_pointer_cast<SQLName>(name->clone());
    name2->setParent(SharedObject(SQLPartitionBy));
    x->storeIn->push_back(name2);
  }

  x->lifecycle = lifecycle;
}

BOOL_ptr SQLPartitionBy::isPartitionByColumn(long columnNameHashCode64)
{
  for (SQLExpr_ptr column : *columns)
  {
    if (instanceof <SQLExpr, SQLIdentifierExpr>(column) && (std::dynamic_pointer_cast<SQLIdentifierExpr>(column)->nameHashCode64() == columnNameHashCode64))
    {
      return BOOL::TRUE;
    }
  }

  if (subPartitionBy != nullptr)
  {
    return subPartitionBy->isPartitionByColumn(columnNameHashCode64);
  }
  return BOOL::FALSE;
}

SQLIntegerExpr *SQLPartitionBy::getLifecycle()
{
  return lifecycle;
}

void SQLPartitionBy::setLifecycle(SQLIntegerExpr *lifecycle)
{
  this->lifecycle = lifecycle;
}
